﻿using System;
using System.Threading;
using System.Windows.Forms;

namespace EcanPicTools
{
    public partial class Form1 : Form
    {
        private static Mutex Mutex1, Mutex2, Mutex3, Mutex4, Mutex5;//创建Mutex对象(调度指令) 
        private static AutoResetEvent Event1 = new AutoResetEvent(false);//线程结束信息灯,未结束false,结束true 
        private static AutoResetEvent Event2 = new AutoResetEvent(false);
        private static AutoResetEvent Event3 = new AutoResetEvent(false);
        private AutoResetEvent[] EventS = new[] { Event1, Event2, Event3 };//线程组结束信息灯 

        private delegate void ChangeString(string Txt);//这个代理能异步调用设置文本框(可以多参数) 

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = " ";
            button1.Enabled = false;
            Mutex1 = new Mutex(true);//Mutex对象(一个调度指令) 
            Mutex2 = new Mutex(true);
            Mutex3 = new Mutex(true);
            Mutex4 = new Mutex(true);
            Mutex5 = new Mutex(true);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "多线程调度例子 ");//主线程暂停时，更新进度信息 
            Thread T1 = new Thread(new ThreadStart(Thread1));//定义4个线程 
            Thread T2 = new Thread(new ThreadStart(Thread2));
            Thread T3 = new Thread(new ThreadStart(Thread3));
            Thread T4 = new Thread(new ThreadStart(Thread4));
            T1.Start();//   使用Mutex.WaitAll()方法等待一个Mutex数组（Mutex4和Mutex5）中的对象全部被释放 
            T2.Start();//   使用Mutex.WaitOne()方法等待Mutex3的释放 
            T3.Start();//   使用Mutex.WaitAny()方法等待一个Mutex数组中任意一个对象被释放 
            T4.Start();//   使用WaitHandle.WaitAll等待所有线程结束 
            Thread.Sleep(10);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "分五个线程调度指令Mutex1－－Mutex5 ");//主线程暂停时，更新进度信息 
            Thread.Sleep(2000);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "主线程中释放Mutex1 ");//主线程暂停时，更新进度信息 
            Mutex1.ReleaseMutex();   //线程Thread3结束条件满足 
            Thread.Sleep(2000);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "主线程中释放Mutex3 ");//主线程暂停时，更新进度信息 
            Mutex3.ReleaseMutex();   //线程Thread2结束条件满足 
            Thread.Sleep(2000);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "主线程中释放Mutex4 ");//主线程暂停时，更新进度信息 
            Mutex4.ReleaseMutex();
            Thread.Sleep(2000);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "主线程中释放Mutex5 ");//主线程暂停时，更新进度信息 
            Mutex5.ReleaseMutex();   //线程Mutex1结束条件满足 
            button1.Enabled = true; 
        }

        /// <summary>
        /// 等待Mutex1和Mutex2都被释放 
        /// </summary>
        public void Thread1()
        {
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), new object[] { "线程Thread1启动，Mutex.WaitAll，等待Mutex4和Mutex5都释放信号 " });//从VS2005开始，给主线程控件附值被认为是不安全的 
            Mutex[] gMs = new Mutex[2];
            gMs[0] = Mutex4;//创建一个Mutex数组作为Mutex.WaitAll()方法的参数 
            gMs[1] = Mutex5;
            WaitHandle.WaitAll(gMs);//等待Mutex1和Mutex2都被释放 
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread1结束 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
            Event1.Set();   //线程结束，将Event1设置为有信号状态 
        }

        /// <summary>
        /// 等待Mutex3被释放 
        /// </summary>
        public void Thread2()
        {
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread2启动，Mutex3.WaitOne，等待Mutex3释放信号 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
            Mutex3.WaitOne();//等待Mutex3被释放 
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread2结束 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
            Event2.Set();//线程结束，将Event2设置为有信号状态 
        }

        /// <summary>
        /// 等待数组中任意一个（Mutex1、Mutex2）对象被释放[结束] 
        /// </summary>
        public void Thread3()
        {
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread3启动，Mutex.WaitAny，等待Mutex1和Mutex2中的一个释放信号 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
            Mutex[] gMs = new Mutex[2];
            gMs[0] = Mutex1;//创建一个Mutex数组作为Mutex.WaitAny()方法的参数 
            gMs[1] = Mutex2;
            WaitHandle.WaitAny(gMs);//等待数组中任意一个Mutex对象被释放 
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread3结束 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
            Event3.Set();//线程结束，将Event3设置为有信号状态 
        }

        /// <summary>
        /// 等待所有线程结束
        /// </summary>
        public void Thread4()
        {
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread4启动，WaitHandle.WaitAll，等待所有线程结束 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
            WaitHandle.WaitAll(EventS);
            richTextBox1.Invoke(new ChangeString(SetrichTextBox1Text), "线程Thread4结束，所有线程结束 ");//从VS2005开始，给主线程控件附值被认为是不安全的 
        }

        private void SetrichTextBox1Text(string Txt)//此部分实际上是主线程调用的(可以多参数) 
        {
            richTextBox1.Text += Txt + "\r\n ";
            richTextBox1.Refresh();
        } 

    }
}
